package org.example.juc.question;

import java.util.function.IntConsumer;

//010203040506
public class ZeroEvenOddSolution {
    private int n;
    private volatile int num = 0;

    public static void main(String[] args) {
        ZeroEvenOddSolution solution = new ZeroEvenOddSolution(3);
        Thread thread1 = new Thread(()-> {
            try {
                solution.zero(System.out::print);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });

        Thread thread2 = new Thread(()-> {
            try {
                solution.even(System.out::print);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });

        Thread thread3 = new Thread(()-> {
            try {
                solution.odd(System.out::print);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });

        thread1.start();
        thread2.start();
        thread3.start();

        try {
            thread1.join();
            thread2.join();
            thread3.join();
        } catch (Exception e) {
            System.out.println(e);
        }
    }

    public ZeroEvenOddSolution(int n) {
        this.n = n;
    }

    // printNumber.accept(x) outputs "x", where x is an integer.
    public void zero(IntConsumer printNumber) throws InterruptedException {
        synchronized (this) {
            while (checkNum(num)) {
                while (num % 2 == 0) {
                    printNumber.accept(0);
                    num++;
                    notifyAll();
                }
                wait();
            }
            notifyAll();
        }
    }

    public void even(IntConsumer printNumber) throws InterruptedException {
        synchronized (this) {
            while (checkNum(num)) {
                while (num % 4 == 3) {
                    printNumber.accept((num + 1) / 2);
                    num++;
                    notifyAll();
                }
                wait();
            }
        }
    }

    public void odd(IntConsumer printNumber) throws InterruptedException {
        synchronized (this) {
            while (checkNum(num)) {
                if (num % 4 == 1) {
                    printNumber.accept((num + 1) / 2);
                    num++;
                    notifyAll();
                }
                wait();
            }

        }
    }

    private boolean checkNum(int num) {
        if (num < 2 * n) {
            return true;
        }
        return false;
    }
}
